#include <stdio.h>
#include <time.h>
#include <string.h>
#include <curl/curl.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>  
#include <openssl/bio.h>  
#include <openssl/evp.h>  
#include <openssl/buffer.h>
#include <jansson.h>  
  
// 签名函数
char *sign(const char *application, long timestamp, const char *secret, const char *body) {
    // 连接系统参数
    char sb[1024];
    snprintf(sb, sizeof(sb), "application:%s\ntimestamp:%ld\n", application, timestamp);

    // 连接请求参数
    if (body != NULL && strlen(body) > 0) {
        strcat(sb, body);
        strcat(sb, "\n");
    }
    printf("to sign str is : %s ", sb);
    unsigned char bytes[20] = {0};
    HMAC_CTX ctx;
    HMAC_CTX_init(&ctx);
    HMAC_Init_ex(&ctx, secret, strlen(secret), EVP_sha1(), NULL);
    HMAC_Update(&ctx, sb, strlen(sb));
    HMAC_Final(&ctx, bytes, NULL);
    HMAC_CTX_cleanup(&ctx);

    printf("bytes is : ");
    for (size_t i = 0; i < 20; ++i) {
        printf("%02X", bytes[i]);
    }
    printf("\n");

    // base64编码
    BIO *bmem, *b64;
    BUF_MEM *bptr;
    b64 = BIO_new(BIO_f_base64());
    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, bytes, 20);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);

    char *encryptedString = (char *)malloc(bptr->length + 1);
    memcpy(encryptedString, bptr->data, bptr->length);
    encryptedString[bptr->length] = '\0';

    // 释放资源
    BIO_free_all(b64);

    return encryptedString;
}

// 回调函数，用于接收服务器响应的数据
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
    size_t total_size = size * nmemb;
    char *response = (char *)userdata;
    
    // 将接收到的数据拼接到缓冲区中
    strncat(response, (char *)ptr, total_size);
    
    return total_size;
}

// 将字节序列转换为十六进制字符串表示
void bytes_to_hex(const unsigned char *bytes, size_t len, char *hex) {
    const char *hex_chars = "0123456789abcdef";
    for (size_t i = 0; i < len; i++) {
        hex[i * 2] = hex_chars[(bytes[i] >> 4) & 0x0F];
        hex[i * 2 + 1] = hex_chars[bytes[i] & 0x0F];
    }
    hex[len * 2] = '\0';
}

int main() {
    struct timespec ts;  
    clock_gettime(CLOCK_REALTIME, &ts);  
    long long milliseconds = (long long)ts.tv_sec * 1000LL + ts.tv_nsec / 1000000;
    // long long milliseconds = 1711120305882;

    char time_str[16] = {0};
    char timestamp_str[32] = {0};
    char timestamp_head_str[32] = {0};
    char signature_str[512] = {0};
    sprintf(time_str, "%lld", milliseconds);
    sprintf(timestamp_str, "timestamp:%lld", milliseconds);
    sprintf(timestamp_head_str, "timestamp: %lld", milliseconds);

    const char *application = "cpPA827Z6H4";
    const char *secret = "N6C5677yPw";

    // char *signature = sign(application, milliseconds, secret, "MasterKey:30c96e4516d348f18ef23dd1983bf5fa\npageNow:\npageSize:\nproductId:17060991\nsearchValue:");
    char *signature = sign(application, milliseconds, secret, "{\"productId\":\"17060991\",\"deviceId\":\"8779f9e4a35742c7a19ebea54912b766\",\"datasetId\":\"APPdata\"}");
    if (signature == NULL) {
        printf("Failed to generate signature\n");
        return 1;
    }

    memset(signature_str, 0, 512);
    sprintf(signature_str, "signature: %s", signature);
    printf("Base64 encoded SHA-256 hash : %s\n", signature);

    free(signature);

    CURL *curl;
    CURLcode res;

    struct curl_slist *headers = NULL;

    // 初始化libcurl
    curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "Failed to initialize libcurl\n");
        return 1;
    }

    // 设置要访问的URL
    curl_easy_setopt(curl, CURLOPT_URL, "https://2000470318.api.ctwing.cn/aep_device_status/deviceStatus");

    // 设置要使用的SSL/TLS版本
    // curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);

    // 设置 SSL 选项
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    // 设置请求头
    headers = curl_slist_append(headers, "application: cpPA827Z6H4");
    headers = curl_slist_append(headers, signature_str);
    headers = curl_slist_append(headers, "version: 20181031202028");
    headers = curl_slist_append(headers, "Content-Type: application/json; charset=UTF-8");
    headers = curl_slist_append(headers, timestamp_head_str);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    const char* data = "{\"productId\":\"17060991\",\"deviceId\":\"8779f9e4a35742c7a19ebea54912b766\",\"datasetId\":\"APPdata\"}";
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);

    struct curl_slist *temp = headers;
    while (temp) {
        printf("%s\n", temp->data);
        temp = temp->next;
    }

    char response[10240] = {0};
    long response_code = 0;
    // 设置回调函数，接收服务器响应的数据
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
    // 设置接收服务器响应的字符串
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
    // 设置接收服务器响应的状态码
    // curl_easy_setopt(curl, CURLOPT_RESPONSE_CODE, &response_code);

    // 发送POST请求
    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "Failed to perform GET request: %s\n", curl_easy_strerror(res));
        curl_easy_cleanup(curl);
        return 1;
    }
    printf("response is : %s\n", response);

    json_error_t error;
    json_t *root = json_loads(response, 0, &error);
    if (!root) {
        printf("parse json error.\n");
    } else {
        json_t *status = json_object_get(root, "deviceStatus");
        if (json_is_object(status)) {
            json_t *valueJson = json_object_get(status, "value");
            if (json_is_string(valueJson)) {
                const char* value = json_string_value(valueJson);
                printf("\n\nvalue is %s\n", value);

                // 解码 Base64 字符串
                BIO *bio = BIO_new(BIO_s_mem());
                BIO_puts(bio, value);
                BIO *b64 = BIO_new(BIO_f_base64());
                BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
                bio = BIO_push(b64, bio);
                
                // 计算解码后的字节长度
                size_t decoded_len = strlen(value) * 3 / 4;
                unsigned char *decoded_data = (unsigned char *)malloc(decoded_len);
                
                // 解码
                int decoded_size = BIO_read(bio, decoded_data, decoded_len);
                if (decoded_size < 0) {
                    fprintf(stderr, "Error decoding Base64\n");
                    return 1;
                }
                BIO_free_all(bio);
                
                // 将解码后的字节序列转换为十六进制字符串
                char *hex_str = (char *)malloc(decoded_size * 2 + 1);
                bytes_to_hex(decoded_data, decoded_size, hex_str);
                
                printf("Hex string: %s\n", hex_str);
                
                free(decoded_data);
                free(hex_str);
            }
        }

        json_decref(root);
    }

    // 清理并释放libcurl资源
    curl_easy_cleanup(curl);

    return 0;
}

